package com.jardecompiler.controller;

import com.jardecompiler.service.DecompilerService;
import com.jardecompiler.util.SessionMultipartFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import jakarta.servlet.http.HttpSession;

/**
 * JAR反编译控制器 - 处理Web请求，实现JAR文件上传、反编译和结果展示功能。
 * 
 * **作者**: huruifeng
 * **开源协议**: MIT License
 */
@RestController
public class DecompilerController {

    @Autowired
    private DecompilerService decompilerService;

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @PostMapping("/upload")
    public String uploadJar(@RequestParam("jarFile") MultipartFile file,
                           Model model,
                           RedirectAttributes redirectAttributes,
                           HttpSession session) {

        if (file.isEmpty()) {
            redirectAttributes.addFlashAttribute("error", "Please select a JAR file to upload.");
            return "redirect:/";
        }

        String fileName = file.getOriginalFilename();
        if (fileName == null || !fileName.toLowerCase().endsWith(".jar")) {
            redirectAttributes.addFlashAttribute("error", "Please upload a valid JAR file.");
            return "redirect:/";
        }

        try {
            String projectStructure = decompilerService.decompileJar(file);

            // Store file information in session for download
            session.setAttribute("uploadedFileName", fileName);
            session.setAttribute("uploadedFileSize", file.getSize());
            session.setAttribute("uploadedFileBytes", file.getBytes());

            model.addAttribute("projectStructure", projectStructure);
            model.addAttribute("fileName", fileName);
            model.addAttribute("fileSize", formatFileSize(file.getSize()));
            return "result";

        } catch (Exception e) {
            redirectAttributes.addFlashAttribute("error",
                "Error decompiling JAR file: " + e.getMessage());
            return "redirect:/";
        }
    }

    @PostMapping("/download")
    public ResponseEntity<byte[]> downloadDecompiledProject(HttpSession session) {
        try {
            // Get file information from session
            String originalFileName = (String) session.getAttribute("uploadedFileName");
            byte[] fileBytes = (byte[]) session.getAttribute("uploadedFileBytes");

            if (originalFileName == null || fileBytes == null) {
                return ResponseEntity.badRequest().build();
            }

            // Create a temporary MultipartFile from session data
            MultipartFile file = new SessionMultipartFile(originalFileName, fileBytes);
            byte[] zipData = decompilerService.createProjectZip(file);

            String fileName = originalFileName.replace(".jar", "-decompiled.zip");

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", fileName);
            headers.setContentLength(zipData.length);

            return new ResponseEntity<>(zipData, headers, HttpStatus.OK);

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    @GetMapping("/api/health")
    @ResponseBody
    public ResponseEntity<String> health() {
        return ResponseEntity.ok("JAR Decompiler Service is running");
    }

    private String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.1f KB", size / 1024.0);
        } else {
            return String.format("%.1f MB", size / (1024.0 * 1024.0));
        }
    }
}
